package main

import (
	"fmt"
	"reflect" // 反射
	"unsafe"  // unsafe包配合uintptr可以绕过go的安全检查，对内存进行操作
)

func String(b []byte) (s string) {
	// 构造 SliceHeader
	pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	/*
		Len：代表切片的长度
		Cap：代表切片的容量
		Data：指向具体的底层数组
	*/
	fmt.Println(pbytes.Len, pbytes.Cap, pbytes.Data, pbytes)
	// 构造一个空的 StringHeader
	pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
	fmt.Println(pstring.Len, pstring.Data, pstring)

	// 这样相当于将 slice 的内存地址 复制给 string 的内存地址上
	pstring.Data = pbytes.Data
	// string 的长度重新被定义
	pstring.Len = pbytes.Len
	return
}

func Slice(s string) (b []byte) {
	// 构造一个空的 SliceHeader
	pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
	// 构造 StringHeader
	pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
	pbytes.Data = pstring.Data
	pbytes.Len = pstring.Len
	pbytes.Cap = pstring.Len
	return
}

func main() {
	//a := []byte("hello world")
	//b := String(a)
	//c := string(a)
	//a[0] = 'a'
	//fmt.Println(a)
	//fmt.Println(b) //output  aello world
	//fmt.Println(c)

	x := "hello world"
	y := Slice(x)
	fmt.Println(y)
	//y[0] = 'a' //这里就等着崩溃吧 猜测string是immutable的，可能对应的内存地址也是不允许改动的
	//但是可以这样，因为go又重新给y分配了内存
	y = append(y, "hello world"...)
	fmt.Println(y)
	y[0] = 'a'
	fmt.Println(y)
}
